Lexical Environment(정적 환경)
var point = 123;
function book() {
function getPoint() {}
}
book();
-
엔진이 쭉 문자열로 된 코드를 읽다가, 2번 째 줄의 function 키워드를 만나면 function object를 생성하고, 현재 스코프를 function object의
[[Scope]]
에 설정한다. 함수 내부는 알 수 없다. 아직 함수 외부에서 코드를 읽고 있기 때문이다. 이 시점(엔진이 function 키워드를 만났을 때)에서 함수의 외부(Lexical Environment) 스코프가 결정된다.- es3에서는 호출시에 scope chain을 동적을 바꿔갔지만, es5에서는 엔진이 해석하는 단계에서 함수의 환경을 결정했다.(정적이다.)
-
함수가 호출되면(5번 째 줄), function object의
[[Scope]]
에 저장된 것을 execution context의 lexical environment component(LEC) -> 외부 렉시컬 환경 참조에 설정한다.- 여기서 실행 컨텍스트는 함수 호출 시에 생성됨을 알 수 있다.
- LEC 내부에는 선언적 환경 레코드도 존재하는데, 여기는 함수 내부에 선언된 변수나 함수가 K/V로 들어간다.
-
하나의 context에 들어갈 수 있도록 코딩을 하면, 메모리에 들락날락 거릴 필요 없어져, 엔진이 빠르게 동작할 수 있게된다.
But, Lexical Env에서 var 키워드 문제
-
함수에서 var 키워드를 사용하지 않고 변수를 선언하면(
a = 10
), 글로벌 오브젝트에 설정된다. 현재 생성되는 컨텍스트가 글로벌 오브젝트로부터 X 단계 상위에 위치한다면, 타고 타고 올라가서 글로벌 오브젝트에서 식별자를 찾아와야한다. -
그러나, Lexical Environment는 function 키워드를 만났을 때, 그 외부 Scope 저장해 놓으므로, 글로벌 오브젝트에 설정된 변수를 참조할 수가 없다. (정적 환경에서는 함수 내부와 바로 외부, 두 개의 범위만 알고 있을 수 있다.)
해결책
-
ES5에서는
"use strict"
를 사용하면서 해결했다.use strick
모드에선, 변수 선언 시var
키워드를 빼면 에러가 난다. 근본적인 해결은 아닌듯
-
ES6에서는
let
과const
변수- 변수 자체에 Scope 제약을 둬서 lexical env를 유지하려고 한 것이다.
동적 환경
자바스크립트에는 동적 환경도 존재한다. 지금까지는 function 키워드를 만나면, 그때 Scope가 결정되었지만, 함수 실행 될 때마다 Scope가 만들어지게 만들 수 있다.
-
with 문
- JS 엔진은 with 문을 만나면 Scope를 생성한다. 반복문으로 with를 이뤄지면 루프만큼 scope를 생성하게 된다.
- 그러나 with문은 strict 모드에선 에러가 발생한다. 따라서 use strict 사용으로 with문 사용을 배제할 수 있다.
-
eval() 함수
- 문자열에 감싸진 코드를 인자로 사용하기 때문에 막는 방법이 없다.
- 그러나 보안에 문제가 있으므로 최대한 사용하지 말자. (어떤 문제가 있는지 알아보자.)